package com.fengmi.security;

import cn.hutool.json.JSONUtil;
import com.fengmi.entity.SysUserEntity;
import com.fengmi.util.JwtUtils;
import com.fengmi.util.RsaUtils;
import com.fengmi.vo.ResultVO;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.Collection;

//重写过滤器
public class CustomerBasicAuthenticationFilter extends BasicAuthenticationFilter {
    public CustomerBasicAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //1.获取jwt令牌
        String token = request.getHeader("token");//从请求头中获取token

        //放行登录请求
        String requestURI = request.getRequestURI();
        if ("/user/login".equals(requestURI)){
            chain.doFilter(request, response);
            return;
        }

        //放行认证请求
        if ("/user/check".equals(requestURI)){
            chain.doFilter(request, response);
            return;
        }

        if (StringUtils.isEmpty(token)) {
            //不能放行,直接响应json给客户端
            response(response, new ResultVO(false, "令牌不合法"));
        }

        //2.解析令牌(非法令牌不能放行)
        try {
            //获取公钥
            PublicKey publicKey = RsaUtils.getPublicKey(ResourceUtils.getFile("classpath:rsa.pub").getPath());

            //解析公钥 获取令牌中的用户信息
            SysUserEntity sysUser = (SysUserEntity) JwtUtils.getInfoFromToken(token, publicKey, SysUserEntity.class);

            //3.将用户的信息放入security的context中
            //将用户的权限和角色信息封装成List
            Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(sysUser.getRoels()+","+sysUser.getPermssions());

            //放入security
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(sysUser, null, authorities);
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

            //放行
            chain.doFilter(request,response);
        } catch (Exception e) {
            e.printStackTrace();

            response(response, new ResultVO(false, "令牌不合法"));
        }
    }

    //封装的响应方法
    private void  response(HttpServletResponse response, ResultVO res) {
        try {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            PrintWriter out = response.getWriter();

            out.write(JSONUtil.toJsonStr(res));
            out.flush();
            out.close();
        } catch (Exception e) {

        }
    }
}
